package com.gopay.common.cipher.utils;


import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.gopay.common.cipher.constants.SensitiveInfoConstants;


/**
 * 
 * @ClassName: DictionaryUtils 
 * @Description: 将加解密的密文与明文，用户密码等的sha1结果与sha512结果发送到mq， 
 * @author zyt 
 * @date 2016年12月29日 下午2:39:53
 */
public class SensitiveInfoDictionaryUtils {
	
	private final static Log logger = LogFactory.getLog("SensitiveInfoDictionaryUtils");
	
	public static final String CIPHER_TYPE = "cipher";
	
	public static final String PWD_TYPE = "password";
	
	public static final String SMS_TYPE = "sms";
	
	public static final String SPLIT_REGEX = ":";
	
	public static final String SMS_NAME = "smsForException";
	
	/**
	 * MQ 配置文件相关
	 */
	private static final String MQ_URI = "activemq.uri";
	
	private static final String MQ_USER = "activemq.userName";
	
	private static final String MQ_PWD = "activemq.password";
	
	private static final String DIC_QUEUE = "activemq.queue";
	
	private static final String MQ_INUSE = "activemq.inuse";
	
	private static ConnectionFactory connectionFactory;
	private static Connection connection;
	private static Session session;
	private static MessageProducer producer;
	//是否启动mq应急
	private static Boolean isMqInuse = false; 
	private static String user; 
	private static String password; 
	private static String url; 
	private static String queue; 
	
	/**
	 * 
	 * @Description: 		初始化mq连接  
	 * @author princezhaoyt
	 * @throws JMSException 
	 */
	private static void init() throws Exception{
		//如果配置不使用mq，则不去初始化
		if(isMqInuse) {
	        connectionFactory = new ActiveMQConnectionFactory(user, password, url);
			connection = connectionFactory.createConnection();
			connection.start();
			session = connection.createSession(Boolean.TRUE,
	                Session.AUTO_ACKNOWLEDGE);
			Destination destination = session.createQueue(queue);
			producer = session.createProducer(destination);
		}
	}
	
	/**
	 * 
	 * @Description: 			将密文、明文发到mq 
	 * @param cipherContext		密文
	 * @param context 			明文
	 * @author princezhaoyt
	 */
	public static void sendCipherContextAndContext(String cipherContext, String context){
		//启用mq应急的时候，才发送
		if(isMqInuse){
			if(StringUtils.isBlank(url) || StringUtils.isBlank(user) || StringUtils.isBlank(password) || StringUtils.isBlank(queue)){
				initializeParams();
			}
			try {
				if(connectionFactory == null ||
					connection == null ||
					session == null ||
					producer == null){
				init();
				}
				TextMessage message;
				//判断密文与明文的格式，格式正确，才发送到mq
				if(cipherContext.contains(SensitiveInfoConstants.ENCRYPT_COMMON_MARK) &&
						!context.contains(SensitiveInfoConstants.ENCRYPT_COMMON_MARK)){
					String content = getCombContext(cipherContext, context);
					try{
						message = session.createTextMessage(content);
						producer.send(message);
						session.commit();
					} catch (JMSException je){
						logger.error("发送异常：" , je);
						logger.error("尝试重新连接.....");
						init();
						message = session.createTextMessage(content);
						producer.send(message);
						session.commit();
					}
		            logger.debug("发送成功，消息:" + content);
				}
			} catch (Exception e) {
				handleDicException(cipherContext, context);
				logger.error(e);
			}
		}
	}
	
	/**
	 * 
	 * @Description: 		将sha512与sha1出来的密码，支付密码，安全问题等等，作为字典，存入到字典表中 
	 * @param sha512Pwd		sha512处理的结果
	 * @param sha1Pwd 		sha1处理的结果
	 * @author zyt
	 */
	public static void sendDiffShaPwd(String sha512Pwd, String sha1Pwd){
		//启用mq应急的时候，才发送
		if(isMqInuse){
			if(StringUtils.isBlank(url) || StringUtils.isBlank(user) || StringUtils.isBlank(password) || StringUtils.isBlank(queue)){
				initializeParams();
			}
			try {
				if(connectionFactory == null ||
					connection == null ||
					session == null ||
					producer == null){
				init();
				}
				TextMessage message;
				//拼接消息类型与消息体，并发送消息
				try{
					message = session.createTextMessage(PWD_TYPE + SPLIT_REGEX + sha512Pwd + SPLIT_REGEX +  sha1Pwd);
					producer.send(message);
					session.commit();
				} catch (JMSException je){
					logger.error("发送异常：" , je);
					logger.error("尝试重新连接.....");
					init();
					message = session.createTextMessage(PWD_TYPE + SPLIT_REGEX + sha512Pwd + SPLIT_REGEX +  sha1Pwd);
					producer.send(message);
					session.commit();
				}
			}
			catch (Exception e) {
				handleDicException(sha512Pwd, sha1Pwd);
				logger.error(e);
			}
		}
	}
	
	/**
	 * 以短信形式发送异常内容，先发送到mq，mq接收端接受后再发短信
	 * @param exception 待发送的异常
	 */
	public static void sendExceptionSms(Exception exception){
		//启用mq应急的时候，才发送
		if(isMqInuse){
			if(StringUtils.isBlank(url) || StringUtils.isBlank(user) || StringUtils.isBlank(password) || StringUtils.isBlank(queue)){
				initializeParams();
			}
			try {
				if(connectionFactory == null ||
					connection == null ||
					session == null ||
					producer == null){
				init();
				}
				TextMessage message;
				//拼接消息类型与消息体，并发送消息
				try{
					message = session.createTextMessage(SMS_TYPE + SPLIT_REGEX + exception.getMessage());
					producer.send(message);
					session.commit();
				} catch (JMSException je){
					logger.error("发送异常：" , je);
					logger.error("尝试重新连接.....");
					init();
					message = session.createTextMessage(SMS_TYPE + SPLIT_REGEX + exception.getMessage());
					producer.send(message);
					session.commit();
				}
			} catch (Exception e) {
				logger.error(e);
			}
		}
	}
	
	/**
	 * 
	 * @Description: 		发送MQ失败的时候，存储字典信息 
	 * @param cipherContext	密文
	 * @param context 		明文
	 * @author zyt
	 */
	private static void handleDicException(String cipherContext, String context){
		logger.error("存储加密字典失败，密文：" + cipherContext + "   明文：" + context);
	}
	
	/**
	 * 
	 * @Description: 			根据字段类型、密文、明文拼接发送的消息内容 
	 * @param cipherContext		密文
	 * @param context			明文
	 * @return 					待发送消息的内容
	 * @author princezhaoyt
	 */
	private static String getCombContext(String cipherContext, String context){
		return CIPHER_TYPE + SPLIT_REGEX + cipherContext + SPLIT_REGEX + context;
	}
	
	/**
	 * 
	 * @Description: 从配置文件中读取MQ的配置信息 
	 * @author zyt
	 */
	private static void initializeParams(){
		InputStream inputstream = KeyPropertiesUtils.class.getClassLoader().getResourceAsStream(SensitiveInfoConstants.CIPHERPROP_PATH);
        System.out.println(inputstream);
        Properties pathConfig = new Properties();
        Map<String, String> paramsMap = new HashMap<String, String>();
        try {
			pathConfig.load(inputstream);
			isMqInuse = Boolean.parseBoolean(pathConfig.getProperty(MQ_INUSE));
			url = pathConfig.getProperty(MQ_URI);
			user = pathConfig.getProperty(MQ_USER);
			//modified by zyt,2017-7-11，对密码中包含转义字符的情况下，做转义处理
			password = StringEscapeUtils.unescapeHtml3(pathConfig.getProperty(MQ_PWD));
			queue = pathConfig.getProperty(DIC_QUEUE);
		} catch (IOException e) {
			logger.error("读取MQ配置文件失败:" + e);
		}
	}
}
